package com.wink.admin.utils;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;

/**
 * @author donaldhan
 */
public class TokenUtils {

    private static final String AUTHORITIES_KEY = "auth";

    public static final String AUTHORIZATION_HEADER = "Authorization";

    public static final String TOKEN_PREFIX = "Bearer ";

    public static final String TOKEN_TYPE = "JWT";
    // 字节位数有要求
    public static String secret = "vbvbretgfdgdfdsfsdfsdfssssssssssssssssssd";
    private final static Logger logger = LoggerFactory.getLogger(TokenUtils.class);

    /**
     * 生成认证的token
     *
     * @param username   用户名
     * @param secret     秘钥
     * @param data       需要保存的数据
     * @param expireTime 有效期(单位：秒)
     */
    public static String createAuthToken(String username, String secret, Object data, long expireTime) {
        if (StrUtil.isEmpty(username)) {
            logger.error("username不能为空");
            throw new NullPointerException("username不能为空");
        }
        if (StrUtil.isEmpty(secret)) {
            logger.error("secret密钥不能为空");
            throw new NullPointerException("secret密钥不能为空");
        }
        if (ObjectUtil.isEmpty(data)) {
            logger.error("data不能为空");
            throw new NullPointerException("data不能为空");
        }
        if (expireTime <= 0L) {
            logger.error("有效时间必须大于0");
            throw new RuntimeException("有效时间必须大于0");
        }

        // 推荐方法:随机生成
        // SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        // String secretString = Encoders.BASE64.encode(key.getEncoded());
        // logger.info("jwt保存秘钥！{}",secretString);
        // 使用自定义的秘钥字符串
        Key key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
        // 这里巨坑 必须添加一个json序列化的jwt依赖，总共3个依赖
        return Jwts.builder()
                .setHeaderParam("type", TOKEN_TYPE)
                // 签名设置
                .signWith(key)
                .claim("data", data)
                // 发行人
                .setIssuer("wink")
                //创建时间
                .setIssuedAt(new Date())
                .setSubject(username)
                // 有效期设置
                .setExpiration(new Date(System.currentTimeMillis() + (expireTime * 1000)))
                // .setId("1")
                .compact();
    }


    /**
     * token认证
     *
     * @param token  token字符串
     * @param secret 生成token生成的秘钥
     */
    public static Object tokenAuthentication(String token, String secret) {
        if (StrUtil.isNotEmpty(token) && StrUtil.isNotEmpty(secret)) {
            // try {
            Key key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                    // 验签签名
                    .setSigningKey(key).build()
                    // 去掉 Bearer
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""));

            //获取token携带的数据
            return claimsJws.getBody().get("data");
        } else {
            logger.error("token认证失败，参数错误，token或者secret参数为空");
            throw new RuntimeException("token认证失败，参数错误，token或者secret参数为空");
        }

    }
}
